package com.ruoyi.dynamic;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.SuperEntity;
import com.ruoyi.dynamicmenu.BaseUseStatusBuilder;
import com.ruoyi.query.entity.Query;

import java.lang.reflect.Type;
import java.util.Collection;

/**
 * **********************
 * * Author: XiaShiLong *
 * * Date  : 2021-03-26 *
 * * Time  : 13:54      *
 * * to    : lz&xm      *
 * **********************
 * 动态查询服务
 **/
public interface DynamicQueryService<T> extends IService<T> {

    /**
     * 分页查询
     *
     * @param page  页码
     * @param size  每页数量
     * @param query 查询条件对象 <see>Query</see>
     * @return Page
     */
    Page<T> pageQuery(int page, int size, Query query);

    /**
     * 分页查询
     *
     * @param page 页码
     * @param size 每页数量
     * @param sql  sql
     * @return Page
     */
    Page<T> pageQuery(int page, int size, String sql);

    /**
     * 导出
     *
     * @param query 查询条件对象 <see>Query</see>
     * @return ajaxResult
     */
    AjaxResult export(Query query);

    /**
     * 保存
     * 手动操作create(),update()
     *
     * @param entity 对象
     * @return boolean
     */
    default boolean saveNoSuperTime(T entity) {
        return SqlHelper.retBool(getBaseMapper().insert(entity));
    }

    /**
     * 更新
     * 手动操作create(),update()
     *
     * @param entity 对象
     * @return boolean
     */
    default boolean updateByIdNOSuperTime(T entity) {
        return SqlHelper.retBool(getBaseMapper().updateById(entity));
    }

    @Override
    default boolean save(T entity) {
        hitSuperEntity(entity, true);
        return SqlHelper.retBool(getBaseMapper().insert(entity));
    }

    @Override
    default boolean update(T entity, Wrapper<T> updateWrapper) {
        hitSuperEntity(entity, false);
        return SqlHelper.retBool(getBaseMapper().update(entity, updateWrapper));
    }

    @Override
    default boolean updateById(T entity) {
        hitSuperEntity(entity, false);
        return SqlHelper.retBool(getBaseMapper().updateById(entity));
    }

    @Override
    default boolean updateBatchById(Collection<T> entityList) {
        return updateBatchById(entityList, DEFAULT_BATCH_SIZE);
    }

    @Override
    boolean updateBatchById(Collection<T> entityList, int batchSize);

    @Override
    default boolean saveBatch(Collection<T> entityList) {
        return saveBatch(entityList, DEFAULT_BATCH_SIZE);
    }

    @Override
    boolean saveBatch(Collection<T> entityList, int batchSize);

    /**
     * 超类操作
     *
     * @param isSave true : 保存, false : 更新
     */
    default void hitSuperEntity(T e, boolean isSave) {
        Type t = e.getClass().getGenericSuperclass();
        if (t.getTypeName().equals(SuperEntity.class.getName())) {
            SuperEntity s = (SuperEntity) e;
            if (isSave) {
                s.create();
            } else {
                s.update();
            }
        }
    }

    /**
     * baseUseStatus -> 0 -> 临时
     *
     * @param id 主键
     * @param t  目标对象
     * @return boolean
     */
    default boolean baseUseStatusTemporary(Long id, T t) {
        BaseUseStatusBuilder.temporary(id, t);
        hitSuperEntity(t, false);
        return SqlHelper.retBool(getBaseMapper().updateById(t));
    }

    /**
     * baseUseStatus -> 0 -> 临时
     *
     * @param id 主键
     * @return boolean
     */
    default boolean baseUseStatusTemporary(Long id) {
        return baseUseStatusTemporary(id, getGenericInstance());
    }

    /**
     * baseUseStatus -> 1 -> 正式
     *
     * @param id 主键
     * @param t  目标对象
     * @return boolean
     */
    default boolean baseUseStatusFormal(Long id, T t) {
        BaseUseStatusBuilder.formal(id, t);
        hitSuperEntity(t, false);
        return SqlHelper.retBool(getBaseMapper().updateById(t));
    }

    /**
     * baseUseStatus -> 1 -> 正式
     *
     * @param id 主键
     * @return boolean
     */
    default boolean baseUseStatusFormal(Long id) {
        return baseUseStatusFormal(id, getGenericInstance());
    }

    /**
     * baseUseStatus -> 2 -> 作废
     *
     * @param id 主键
     * @param t  目标对象
     * @return boolean
     */
    default boolean baseUseStatusDisuse(Long id, T t) {
        BaseUseStatusBuilder.disuse(id, t);
        hitSuperEntity(t, false);
        return SqlHelper.retBool(getBaseMapper().updateById(t));
    }

    /**
     * baseUseStatus -> 2 -> 作废
     *
     * @param id 主键
     * @return boolean
     */
    default boolean baseUseStatusDisuse(Long id) {
        return baseUseStatusDisuse(id, getGenericInstance());
    }

    default T getGenericInstance() {
        try {
            return getEntityClass().newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException("instance generic failure!");
        }
    }

    /**
     * 是否存在
     *
     * @param queryWrapper 查询条件对象
     * @return boolean true:存在, false:不存在
     */
    boolean exist(Wrapper<T> queryWrapper);

    /**
     * 保存并返回
     */
    T saveReturn(T entity);
}
